package eu.catengine.renderable;

import java.nio.FloatBuffer;

import eu.catengine.common.iface.IDisposable;
import eu.catengine.common.iface.IRenderable;
import eu.catengine.primitive.Point;
import eu.catengine.primitive.Vector;

/**
 * Klasa przechowująca podstawowe dane dotyczące wyświetlania obiektów w scenie.<br>
 * 
 * @author mbienkowski
 */
public abstract class Renderable implements IRenderable, IDisposable
{
    protected String mName;

    protected float[] mVertices;
    protected int mVerticesCount;
    protected FloatBuffer mVertexBuffer;

    protected long mStartTime;
    protected boolean mVisible = true;
    protected boolean mKeepInScene = true;
    protected boolean mUpdateNeeded = false;

    @Override
    public void setName(String name)
    {
	if (name.equals(""))
	{
	    name = System.identityHashCode(this) + "";
	}

	this.mName = new String(name);
    }

    @Override
    public String getName()
    {
	return mName;
    }

    @Override
    public void setVisible(boolean visible)
    {
	mVisible = visible;
    }

    @Override
    public boolean isVisible()
    {
	return mVisible;
    }

    @Override
    public void setVertices(float[] vertices)
    {
	this.mVertices = vertices;
	this.updateBuffer();
    }

    @Override
    public float[] getVertices()
    {
	return mVertices;
    }

    @Override
    public void setStartTime(long elapsedTime)
    {
	mStartTime = elapsedTime;
    }

    @Override
    public long getStartTime()
    {
	return mStartTime;
    }

    @Override
    public void setUpdateNeeded(boolean updateNeeded)
    {
	mUpdateNeeded = updateNeeded;
    }

    @Override
    public boolean isUpdateNeeded()
    {
	return mUpdateNeeded;
    }

    @Override
    public void setKeepInScene(boolean keepInScene)
    {
	mKeepInScene = keepInScene;
    }

    @Override
    public boolean getKeepInScene()
    {
	return mKeepInScene;
    }

    @Override
    public void updateBuffer()
    {
	this.mVertexBuffer.clear();
	this.mVertexBuffer.put(this.mVertices);
	this.mVertexBuffer.position(0);
    }
    
    @Override
    public Point getAnchorPoint()
    {
	return new Point(mVertices[2], mVertices[3]);
    }

    @Override
    public Point getCenterPoint()
    {
	return new Point((mVertices[0] + mVertices[6]) / 2f, (mVertices[1] + mVertices[7]) / 2f);
    }
    
    @Override
    public boolean isAtPoint(Point point)
    {
	return isAtPoint(point.x, point.y);
    }

    public boolean isAtPoint(float x, float y)
    {
	Vector vectorAB = new Vector(mVertices[0], mVertices[1], mVertices[2], mVertices[3]);
	Vector vectorAP = new Vector(mVertices[0], mVertices[1], x, y);
	Vector vectorBC = new Vector(mVertices[2], mVertices[3], mVertices[6], mVertices[7]);
	Vector vectorBP = new Vector(mVertices[2], mVertices[3], x, y);

	float dotABAP = vectorAB.dotProduct(vectorAP);
	float dotABAB = vectorAB.dotProduct(vectorAB);
	float dotBCBP = vectorBC.dotProduct(vectorBP);
	float dotBCBC = vectorBC.dotProduct(vectorBC);

	return (0 <= dotABAP && dotABAP <= dotABAB && 0 <= dotBCBP && dotBCBP <= dotBCBC);
    }
    
    @Override
    public void dispose()
    {
	mVertexBuffer.clear();
	
	mName = null;
	mVertices = null;
	mVertexBuffer = null;
    }
}
